/*********************************************************************
*
* Software License Agreement (BSD License)
*
*  Copyright (c) 2010, Heriot-Watt University, UK.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Heriot-Watt University nor the names of 
*     its contributors may be used to endorse or promote products 
*     derived from this software without specific prior written
*     permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*
*  Author: Pedro Patron
*
*********************************************************************/

#ifndef _OSLCORE_ITERATOR_H_
#define _OSLCORE_ITERATOR_H_

#if defined(WIN32) || defined(_WIN32)
// Doing nothing
#else
using namespace std;
#endif

namespace osl_core {

/**
 * Defines the protocol to use in the rest of iterator subclass.
 */
template <class T>
class Iterator {
	public:
		
		/**
		 * Initializes the sequence treatment.
		 * @return true if actual element exists, false otherwise
		 */	
		virtual bool	init		() = 0;
		
		/**
		 * @return true if we are not in the end of sequence, false otherwise
		 */
		virtual bool	operator !     	() = 0;

		/**
		 * @return actual element
		 */
		virtual T	operator ()    	() = 0;

		/**
		 * Go to next element
		 * @return true if actual element exists
		 * 
		 * Modify actual element going to the next element 
		 * in the sequence
		 */		
		virtual bool	operator ++    	() = 0;

		/**
		 * Go to next element
		 * @return true if actual element exists
		 *
		 * Modify actual element going to the next element
		 * in the sequence
		 */
		virtual bool	operator ++    	(int) = 0;
		
  		/**
		 * Asign newValue to actual element
		 * @param	newValue	value type T
		 * @return	reference to modified element
		 *
		 * Modify actual element changing its value to newValue
		 */
		virtual T &	operator =     	(const T & newValue) = 0;
};


// Prototypes

/**
 * @param	out	output stream
 * @param	itr	iterator	
 * @return	output stream containing the collection elements
 */
template <class T>
#if defined(WIN32) || defined(_WIN32)
std::ostream & operator << (std::ostream & out, Iterator<T> & itr);
#else
ostream & operator << (ostream & out, Iterator<T> & itr);
#endif

/**
 * Check if a value is inside a collection.
 * @param	itr Iterator
 * @param	x	value type T
 * @return	true if x was found inside the collection
 */
template <class T>
bool includes (Iterator<T> & itr, const T & x);


template <class T>
#if defined(WIN32) || defined(_WIN32)
std::ostream & operator << (std::ostream & out, Iterator<T> & itr)
#else
ostream & operator << (ostream & out, Iterator<T> & itr)
#endif
{
	out << "( ";
	for (itr.init(); !itr; ++itr)
		out << itr() << ' ';
	out << ')';

	return out;
}

template <class T>
bool includes (Iterator<T> & itr, const T & x)
{
	for (itr.init(); !itr; ++itr)
	if (itr() == x)
		return true;
	return false;
}

} // namespace

#endif
